Array.prototype.first = function() {
    return this[0];
};

Array.prototype.last = function() {
    return this[this.length - 1];
};

Array.prototype.foreach = function(func) {
    $.each(this, function(index, item) {
        func(item, index);
    });
};

Array.prototype.findFirst = function(predicate) {
    for (var i = 0; i < this.length; i++) {
        if (predicate(this[i], i)) {
            return this[i];
        }
    }
    return null;
};

Array.prototype.findFirstIndex = function(predicate) {
    for (var i = 0; i < this.length; i++) {
        if (predicate(this[i], i)) {
            return i;
        }
    }
    return -1;
};

Array.prototype.findIndex = function(predicate) {
    var indics = [];
    for (var i = 0; i < this.length; i++) {
        if (predicate(this[i], i)) {
            indics.push(i);
        }
    }
    return indics;
};

Array.prototype.select = function(func) {
    var result = [];
    for (var i = 0; i < this.length; i++) {
        result.push(func(this[i], i));
    }
    return result;
};

Array.prototype.where = function(predicate) {
    return $.grep(this, function(item, index) {
        return predicate(item, index);
    });
};

Array.Same = function(array1, array2, equalFunc) {
    if (array1.length != array2.length) return false;
    for (var i = 0; i < array1.length; i++) {
        if (!equalFunc(array1[i], array2[i])) {
            return false;
        }
    }
    return true;
};

Array.prototype.sum = function(defaultValue, func) {
    var sum = defaultValue;
    this.foreach(function(item) {
        sum = func(item, sum);
    });
    return sum;
};

Array.prototype.continousGroupBy = function(selector) {
    if (this.length == 0) {
        return [];
    }
    var groups = [];
    groups.push([this[0]]);
    for (var i = 1; i < this.length; i++) {
        if (selector(this[i]) == selector(this[i-1])) {
            groups.last().push(this[i]);
        }
        else {
            groups.push([this[i]]);
        }
    }
    return groups;
};

Array.prototype.split = function(predicate) {
    var startElemntIndics = this.findIndex(function(item, index) { return predicate(item, index) });
    var indics = [0].concat(startElemntIndics).concat([this.length]);
    var groups = [];
    for (var i = 1; i < indics.length; i++) {
        var group = this.slice(indics[i - 1], indics[i]);
        if (group.length > 0) {
            groups.push(group);
        }
    }
    return groups;
};    